﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MessageProtocol;
using System.Net;
using System.IO;
using System.Net.Sockets;


namespace Server
{
    class GameServer
    {
        private TcpListener server;
        private TcpClient client;
        private Message reqMsg;
        private Message respMsg;
        byte[] sendByte;
        byte[] receiveByte;
        private NetworkStream stream;
        private static ResultDataManager resultDataManager;

        public GameServer()
        {
            server = null;
        }

        public void Run()
        {
            sendByte = new byte[128];
            receiveByte = new byte[128];

            try
            {
                const int portNum = 843;
                IPEndPoint localAddress = new IPEndPoint(0, portNum);
                server = new TcpListener(localAddress);
                server.Start();

                while (true)
                {
                    // 연결 수립
                    client = server.AcceptTcpClient();

                    Console.WriteLine("클라이언트 IP : {0}",
                        ((IPEndPoint)client.Client.RemoteEndPoint).ToString());

                    stream = client.GetStream();

                    stream.BeginRead(receiveByte, 0, receiveByte.Length,
                        new AsyncCallback(OnReceive), stream);

                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void OnSend(IAsyncResult ar)
        {
            try
            {
                Console.WriteLine("Send To Client");

                stream = (NetworkStream)ar.AsyncState;
                stream.EndWrite(ar);

                stream.BeginRead(receiveByte, 0, receiveByte.Length,
              new AsyncCallback(OnReceive), stream);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void OnReceive(IAsyncResult ar)
        {
            Console.WriteLine("Receive From Client");

            try
            {
                stream = (NetworkStream)ar.AsyncState;
                stream.EndRead(ar);
                reqMsg = MessageController.Decode(new MemoryStream(receiveByte));

                Console.WriteLine("Receive MSGID : " + reqMsg.Header.MSGID);

                MakeResponse(reqMsg.Header.MSGTYPE);

                Console.WriteLine("Created MSG : {0} " ,respMsg.Header.MSGID);
                
                sendByte = respMsg.GetBytes();

                stream.BeginWrite(sendByte, 0, sendByte.Length,
           new AsyncCallback(OnSend), stream);

            }

            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }


        }

        private void MakeResponse(uint type)
        {
            switch (type)
            {
                case MessageConstants.TYPE_REQUEST_SAVE:
                    {
                 
                        BodyRequest reqBody = (BodyRequest)reqMsg.Body;

                        string id = Encoding.Default.GetString(reqBody.PLAYER_NAME);
                        int score = reqBody.SCORE;

                        BodyResponse respBody = new BodyResponse();
                        respBody.MSGID = reqMsg.Header.MSGID;
                        respBody.RESPONSE = 1;

                        Header header = new Header();
                        header.MSGID = reqMsg.Header.MSGID;
                        header.MSGTYPE = MessageConstants.TYPE_REQUEST_SAVE;
                        header.BODYLENGTH = (uint)respBody.GetSize();
                        header.LASTMSG = 1;
                                           
                        respMsg = new Message() { Header = header, Body = respBody };

                        resultDataManager.AddRanking(id, score);
                        break;
                    }

                case MessageConstants.TYPE_REQUEST_GET:
                    {

                        Dictionary<string, int> dataList = resultDataManager.GetAllRanking();

                        foreach (KeyValuePair<string, int> kv in dataList)
                        {
                            BodyRequest reqBody = new BodyRequest();

                            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                            reqBody.PLAYER_NAME = encoding.GetBytes(kv.Key);
                            reqBody.SCORE = kv.Value;

                            Header header = new Header();
                            header.MSGID = reqMsg.Header.MSGID;
                            header.MSGTYPE = MessageConstants.TYPE_REQUEST_GET;
                            header.BODYLENGTH = (uint)reqBody.GetSize();
                            header.LASTMSG = 1;
                        }
                        
                        break;

                    }
                default:
                    break;
            }


        }



        static void Main(string[] args)
        {
            Console.WriteLine("This is Server\n");
            resultDataManager = ResultDataManager.Instance();
            GameServer server = new GameServer();
            server.Run();
            while (true) ;
        }
    }
}
